Fullcalendar v5.5.1 设计一个考勤日历插件 | 您所在的位置:网站首页 › react-calendar 农历 › Fullcalendar v5.5.1 设计一个考勤日历插件 |
前言
最近公司HR项目新增一个考勤日历需求,发现Fullcalendar插件功能齐全,完美支持JQuery、Vue、React 和 Angular,支持TypeScript,开源,并托管在GitHub上。 官方文档:https://fullcalendar.io/ 效果引入依赖文件,当前只展示了主要js,别忘了引入jquery哟 开发Fullcalendar v5相对以前的版本改动较大 Page = { initialLocaleCode: 'zh-cn', initialDate: '', calendar: {}, //fullcalendar 对象 // 初始化Validator initValidator: function () { }, // 事件初期化 initEvents: function () { // 查询按钮按下事件 $(".fn-search").click(Events.searchAction); }, // 画面初始化 initialize: function () { Page.initialDate = $('#today').val(); $(".select2").select2({width: '100%', theme: "lianxin"}); var calendarEl = document.getElementById('calendar'); var calendar = new FullCalendar.Calendar(calendarEl, { headerToolbar: { left: '', center: 'title', right: '' }, initialDate: Page.initialDate, locale: Page.initialLocaleCode, contentHeight: 650, buttonIcons: false, // show the prev/next text weekNumbers: false, navLinks: false, // can click day/week names to navigate views editable: false, dayMaxEvents: true, // allow "more" link when too many events eventOverlap: false, eventLimit: true, eventLimitText : "更多", dayPopoverFormat : "YYYY年M月d日", events: function(arg, callback) { var events = []; $.ajax({ url: webRoot + "/system/attendManage/attendPerson/searchAction.json", data: { attendCycle: $("#attendCycle").val() }, type: "POST", success: function (data) { if(data.success){ data.data.forEach(function (item) { let bgc = '#fff'; let attendDatetime = moment(parseInt(item.attendDatetime) * 1000).format("YYYY-MM-DD"); let title = ''; //入职、离职 if(item.attendStatus && (item.attendStatus.indexOf('11') != -1 || item.attendStatus.indexOf('10') != -1)) { title += ''; title += ''; if(item.attendStatus.indexOf('11') != -1) { title += '入职'; } if(item.attendStatus.indexOf('10') != -1) { title += '离职'; } title += ''; } //打卡 title += ''; let dkBGC = '#fff'; if(item.isLate === '1' || item.isEarly === '1' || item.isAbsent === '1') { dkBGC = 'red'; title += ''; if(item.signinTime || item.signoutTime) { title += ''+item.signinTime+' -- '+item.signoutTime+''; }else { title += ' -- '; } }else { title += ''; if(item.signinTime && item.signoutTime) { title += ''+item.signinTime+' -- '+item.signoutTime+''; } } title += ''; if(item.isLate === '1' || item.isEarly === '1' || item.isAbsent === '1') { let content1 = ''; if(item.isLate === '1') { //迟到 bgc = '#f5d32d'; content1 += '迟到'; } if(item.isEarly === '1') { //早退 bgc = '#f5d32d'; content1 += '早退'; } if(item.isAbsent === '1') { //旷工 bgc = '#f9d9eb'; if(item.absentReason === '1') { content1 += '当天无打卡记录'; }else if(item.absentReason === '2') { content1 += '当天仅一条打卡记录'; }else if(item.absentReason === '3') { content1 += '迟到时间过长'; }else if(item.absentReason === '4') { content1 += '早退时间过长'; } } title += ''+content1+''; } //正常流程 补卡、请假、调休、外出 if(item.isSupplement === '1' || item.isLeave === '1' || item.isDayOff === '1' || (item.attendStatus && item.attendStatus.indexOf('14') != -1)) { title += ''; title += ''; if(item.isSupplement === '1') { title += '补卡'; } if(item.isLeave === '1') { title += '请假'; } if(item.isDayOff === '1') { title += '调休'; } if(item.attendStatus && item.attendStatus.indexOf('14') != -1) { title += '外出'; } title += ''; } events.push({ title: title, start: attendDatetime, display: 'background', color: bgc }); }); //渲染到日历 callback(events); } if(Page.loading) { setTimeout(function () { layer.close(Page.loading); }, 1000) } } }); }, //html内容前置条件,如果没有这一句,自定义的html不生效,必须 eventContent: function(arg, createElement) { var italicEl = document.createElement('span'); italicEl.innerHTML = arg.event._def.title italicEl.className = 'fc-bg-event-span' var arrayOfDomNodes = [italicEl] return { domNodes: arrayOfDomNodes } } }); calendar.render(); Page.calendar = calendar; }, init: function () { Page.initialize(); Page.initEvents(); Page.initValidator(); } }; Events = { // 查询数据 searchAction: function () { Page.loading = layer.load(0, { shade: false, time: 5*1000 }); let gotoDate = moment(Page.initialDate, "YYYY-MM-DD").add(parseInt($("#attendCycle").val()), "months").format("YYYY-MM-DD"); // Page.calendar.removeAllEvents(); Page.calendar.gotoDate(gotoDate); Page.calendar.refetchEvents(); }, } jQuery(document).ready(function () { Page.init(); $("body").click(function(e) { var target = $(e.target); }); }); document.onkeydown = function(event) { if(event.keyCode == 13){ //$("#searchForm").hasClass("active") && // 执行的方法 event.preventDefault(); $("#searchForm").attr("target", ""); //$("#paginator-page").val(1); Events.searchAction(); } } 说明因为默认的Fullcanlendar的样式比较简单直接,所以一般情况下是需要改写样式的。 其他文档最新版的中文文档相对较少,可以参考其他以前版本的资料: $('#calendar').fullCalendar({ /*设置日历头部信息,如果设置为false,则不显示头部信息。 * 包括left,center,right左中右三个位置都可以对应一下配置 * title:显示当前月份/周、日信息 * prev:用于切换到上一月/周/日视图的按钮 * next:用于切换到下一月/周/日视图的按钮 * prevYear:用于切换到上一年视图的按钮 * nextYear:用于切换到下一年视图的按钮 * */ header:{ left: '', center: 'Fullcanlendar示例demo', right: 'today prev,next' }, theme:false,//如果设置为true,则需要加载jquery ui相关css和js文件,默认值为false firstDay:1,//设置一周中显示的第一天是哪天,周日是0,周一是1,类推 isRTL:false,//设置为ture时则日历从右往左显示 weekends:true,//是否显示周末,设为false则不显示周六和周日。默认值为true hiddenDays:[],//隐藏一周中的某一天或某几天,数组形式,如隐藏周二和周五:[2,5],默认不隐藏,除非weekends设置为false。 weekMode:'fixed',//在月视图里显示周的模式,因为每月周数可能不同,所以月视图高度不一定。fixed:固定显示6周高,日历高度保持不变liquid:不固定周数,高度随周数变化variable:不固定周数,但高度固定 weekNumbers:false,//是否在日历中显示周次(一年中的第几周),如果设置为true,则会在月视图的左侧、周视图和日视图的左上角显示周数。 weekNumberCalculation:'iso',//周次的显示格式。 //height:600,//设置日历的高度,包括header日历头部,默认未设置,高度根据aspectRatio值自适应。 //contentHeight://设置日历主体内容的高度,不包括header部分,默认未设置,高度根据aspectRatio值自适应。 aspectRatio:1.35,//设置日历单元格宽度与高度的比例。 handleWindowResize:true,//是否随浏览器窗口大小变化而自动变化。 render:function(view){ console.log('render',view) },//method,绑定日历到id上。$('#id').fullCalendar('render'); destroy:function(){ }, weekNumbers : false, //是否在视图左边显示这是第多少周,默认false eventLimit: true, //数据条数太多时,限制各自里显示的数据条数(多余的以“+2more”格式显示),默认false不限制,支持输入数字设定固定的显示条数 viewRender : function(view,element){//在视图被渲染时触发(切换视图也触发) 参数view为视图对象,参数element为Jquery的视图Dom }, dayRender : function(date, cell){//日期格式Render钩子函数(我没理解清楚) console.log("↓↓↓dayRender↓↓↓"); console.log(date); console.log(cell); }, windowResize : function(){//浏览器窗体变化时触发 console.log("---windowResize---"); }, allDayText : "全天", //自定义全天视图的名称 slotDuration : "01:00:00", //一格时间槽代表多长时间,默认00:30:00(30分钟) slotLabelFormat : "H(:mm)a", //日期视图左边那一列显示的每一格日期时间格式 slotLabelInterval : "02:00:00", //日期视图左边那一列多长间隔显示一条日期文字(默认跟着slotDuration走的,可自定义) snapDuration : "05:00:00", //其实就是动态创建一个日程时,默认创建多长的时间块 slotEventOverlap : false, //相同时间段的多个日程视觉上是否允许重叠,默认true允许 noEventsMessage : "L没数据啊", //listview视图下,无数据时显示提示 defaultDate : '2018-09-10', //默认显示那一天的日期视图getDates(true) nowIndicator : true, //周/日视图中显示今天当前时间点(以红线标记),默认false不显示 monthNames : ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], //月份自定义命名 monthNamesShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], //月份缩略命名(英语比较实用:全称January可设置缩略为Jan) dayNames: ["周日", "周一", "周二", "周三", "周四", "周五", "周六"], //同理monthNames dayNamesShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六"], //同理monthNamesShort weekNumberTitle : "周", //周的国际化,默认为"W" eventLimitText : "更多", //当一块区域内容太多以"+2 more"格式显示时,这个more的名称自定义(应该与eventLimit: true一并用) dayPopoverFormat : "YYYY年M月d日", //点开"+2 more"弹出的小窗口标题,与eventLimitClick可以结合用 navLinks : true, // “xx周”是否可以被点击,默认false,如果为true则周视图“周几”被点击之后进入日视图。本地测试:没什么效果 dayClick: function(date, jsEvent, view) {//空白的日期区,单击时触发 console.log("↓↓↓dayClick↓↓↓"); console.log('Clicked on: ' + date.format()); console.log('Coordinates: ' + jsEvent.pageX + ',' + jsEvent.pageY); console.log('Current view: ' + view.name); //$(this).css('background-color', 'red'); }, eventClick: function(calEvent, jsEvent, view) {//日程区块,单击时触发 console.log(jsEvent.target) alert(jsEvent.target.innerHTML) console.log("↓↓↓eventClick↓↓↓"); console.log('Event: ' + calEvent.title); console.log('Coordinates: ' + jsEvent.pageX + ',' + jsEvent.pageY); console.log('Current view: ' + view.name); return false; //return false可以阻止点击后续事件发生(比如event中的url跳转事件) }, eventMouseover: function(calEvent, jsEvent, view){//鼠标在日程区块上时触发 console.log(jsEvent) console.log(calEvent.start._i) $('.hover-dateStr').html(calEvent.start._i) console.log(jsEvent.pageY,jsEvent.pageX) $('.hover-container').removeClass('none').animate({'top':jsEvent.pageY,'left':jsEvent.pageX}) if(!canRun){ // 判断是否已空闲,如果在执行中,则直接return return; } }, eventMouseout: function(calEvent, jsEvent, view){//鼠标从日程区块离开时触发 $('.hover-container').addClass('none') }, selectable: false, //允许用户可以长按鼠标选择多个区域(比如月视图,可以选中多天;日视图可以选中多个小时),默认false不能选择多区域的 selectHelper: true, //接selectable,周/日视图在选择时是否预先画出“日程区块”的样式出来 unselectAuto : true, //是否点击页面上的其他地方会导致当前的选择被清除,默认true unselectCancel : "", //一种方法来指定元素,会忽略unselectauto选项,默认'' selectOverlap : true, //确定用户是否被允许选择被事件占用的时间段,默认true可占用时间段 selectAllow : function(selectInfo){ //精确的编程控制用户可以选择的地方,返回true则表示可选择,false表示不可选择 console.log("↓↓↓selectConstraint↓↓↓"); console.log("start:"+selectInfo.start+"|end:"+selectInfo.end+"|resourceId:"+selectInfo.resourceId); return true; }, select: function(start, end,jsEvent,view) { //点击空白区域/选择区域内容触发 }, unselect : function(view, jsEvent){//选择操作取消时触发 console.log("↓↓↓unselect↓↓↓"); console.log("view:"+view); }, lazyFetching : true, //是否启用懒加载技术--即只取当前条件下的视图数据,其它数据在切换时触发,默认true只取当前视图的,false是取全视图的 defaultTimedEventDuration : "02:00:00", //在Event Object中如果没有end参数时使用,如start=7:00pm,则该日程对象时间范围就是7:00~9:00 defaultAllDayEventDuration : { days: 1 }, //默认1天是多长,(有的是采用工作时间模式,所以支持自定义) loading : function(isLoading, view){ //视图数据加载中、加载完成触发 console.log("↓↓↓loading↓↓↓"); if(isLoading == true){ console.log("view:"+view+",开始加载"); }else if(isLoading == false){ console.log("view:"+view+",加载完成"); }else{ console.log("view:"+view+",除非天塌下来否则不会进这个分支"); } }, eventOrder : "title", //多个相同的日程数据排序方式,String / Array / Function, 默认值: "title" eventRender : function(event, element, view) { //当Event对象开始渲染时触发 console.log("eventRender():"+event.title); }, eventAfterAllRender : function(view){console.log("eventAfterAllRender();");}, //当所有Event对象渲染完成时触发 editable: true, //支持Event日程拖动修改,默认false eventStartEditable : true, //Event日程开始时间可以改变,默认true,如果是false其实就是指日程块不能随意拖动,只能上下拉伸改变他的endTime eventDurationEditable : false, //Event日程的开始结束时间距离是否可以改变,默认true,如果是false则表示开始结束时间范围不能拉伸,只能拖拽 dragOpacity:0.2, //拖拽时不透明度,0.0~1.0之间,数字越小越透明 dragScroll : true, //是否在拖拽时自动移动容器,默认true eventOverlap : true, //拖拽时是否重叠 eventConstraint : { //限制拖拽拖放的位置(即限制有些地方拖不进去):an event ID, "businessHours", object start: '10:00', // a start time (10am in this example) end: '18:00', // an end time (6pm in this example) dow: [ 1, 2, 3, 4 ] // days of week. an array of zero-based day of week integers (0=Sunday) (Monday-Thursday in this example) }, longPressDelay : 1000, //面向可touch设备(如移动设备),长按多少毫秒即可拖动,默认1000毫秒(1S) eventDragStart : function(event, jsEvent, ui, view){ //日程开始拖拽时触发 console.log("eventDragStart():"+event.title); }, eventDragStop : function(event, jsEvent, ui, view){ //日程拖拽停止时触发 console.log("eventDragStop():"+event.title); }, eventDrop : function(event, delta, revertFunc, jsEvent, ui, view){ //日程拖拽停止并且已经拖拽到其它位置了 console.log("eventDrop():"+event.title); }, eventResizeStart : function( event, jsEvent, ui, view ) { //日程大小调整开始时触发 console.log("eventResizeStart():"+event.title); }, eventResizeStop : function(event, jsEvent, ui, view){ //日程大小调整停止时触发 console.log("eventResizeStop():"+event.title); }, eventResize : function(event, delta, revertFunc, jsEvent, ui, view){ //日程大小调整完成并已经执行更新时触发 console.log("eventResize():"+event.title); }, events:[ { "time": "9:20--18:20", "antualTime":"9:40--18:40", "start": "2018-09-01" }, { "time": "9:40--18:40", "antualTime":"9:40--18:40", "start": "2018-09-02" } ] });FullCalendar提供了很多日程事件的属性设置、方法调用以及回调函数,方便开发者快速掌握FullCalendar。 Event Object Event Object 是一个 js 对象,存储日历表的日程事件信息,支持以下属性: 属性说明idstring 或者 int 类型,事件的唯一标识。重复事件的不同实例应该都具有相同的ID。titleString,必选,事件名称。allDay布尔型,true或false,可选项。 事件是否发生在特定的时间。 该属性影响是否显示事件的时间。 此外,在议程视图中,确定是否显示在“全天”部分。start事件开始日期/时间,必选。格式为ISO8601字符串或UNIX时间戳end事件结束日期/时间,可选。格式为ISO8601字符串或UNIX时间戳url事件链接地址,字符串,可选。 当单击事件的时候会跳转到对应的url。classNamestring 或者 Array 类型,可选。 一个css类(或者一组),附加到事件的 DOM 元素上。editabletrue或false,可选。 只针对当前的单个事件,其他事件不受影响。startEditabletrue或false,可选。 覆盖当前事件的eventStartEditable选项durationEditabletrue或false,可选。 覆盖当前事件的eventDurationEditable选项resourceEditabletrue或false,可选。 覆盖当前事件的 eventResourceEditable选项rendering允许渲染事件,如背景色等。可以为空,也可以是"background", or"inverse-background"overlaptrue或false,可选。 覆盖当前事件的eventOverlap选项。 如果设置为false,则阻止此事件被拖动/调整为其他事件。 还可以防止其他事件在此事件中被拖动/调整大小。constraint事件id,"businessHours",对象,可选。 覆盖当前事件的eventConstraint选项。sourceEvent Source Object事件源color和 eventColor 作用一样,设置事件的背景色和边框。backgroundColor和 eventBackgroundColor 作用一样,设置事件的背景色。borderColor和 eventBorderColor 作用一样,设置事件的边框。textColor和 eventTextColor 作用一样,设置事件的文字颜色除上述属性外,你还可以自定义非标准的属性字段,FullCalendar不会修改或删除这些字段。 Event Source Object "event source"是Fullcalendar的事件数据源events,可以是你定义的一个数组,一个函数,一个返回json的接口,或者google calendar。 数组类型: { events: [ { title: 'Event1', start: '2011-04-04' }, { title: 'Event2', start: '2011-05-05' } // etc... ], color: 'yellow', // an option! textColor: 'black' // an option! }函数: { events: function(start, end, timezone, callback) { // ... }, color: 'yellow', // an option! textColor: 'black' // an option! }json数据: { url: '/myfeed.php', color: 'yellow', // an option! textColor: 'black' // an option! }Events事件源提供了很多属性可以设置: 属性说明id当前事件源的id。可选,见getEventSourceById.color设置事件对象的color(颜色)属性。backgroundColor设置事件对象的backgroundColor(背景色)属性。borderColor设置事件对象的borderColor(边框色)属性。textColor设置事件对象的textColor(文本色)属性。className设置事件对象的className(class类名)属性。editable设置事件对象的editable(可编辑)属性。startEditable设置事件对象的startEditable属性。durationEditable设置事件对象的durationEditable属性。backgroundColor设置事件对象的resourceEditable属性。rendering设置事件对象的rendering属性。overlap设置事件对象的overlap属性。constraint设置事件对象的constraint属性。allDayDefault设置allDayDefault选项,仅限当前事件源。eventDataTransform设置eventDataTransform回调,仅限当前事件源。events (as a function) 自定义函数返回 Event Objects function( start, end, timezone, callback ) { }FullCalendar 会在需要数据的时候调用这个自定义函数,例如当用户切换视图的时候。 此函数会传入 start 和 end参数(Date对象)来表示时间范围。timezone是指Fullcalendar当前使用的时区。另外还有 callback 函数,当自定义函数生成日程之后必须调用,callback的入参是 Event Objects 数组。 以下代码告诉我们如何使用事件函数加载XML格式的数据。 $('#calendar').fullCalendar({ events: function(start, end, timezone, callback) { $.ajax({ url: 'myxmlfeed.php', dataType: 'xml', data: { // our hypothetical feed requires UNIX timestamps start: start.unix(), end: end.unix() }, success: function(doc) { var events = []; $(doc).find('event').each(function() { events.push({ title: $(this).attr('title'), start: $(this).attr('start') // will be parsed }); }); callback(events); } }); } });多个事件源可以使用eventSources。 eventSources eventSources 是一种指定多个数据源的途径,值为数组类型。eventSources 是 events选项的一种替代。 在eventSources里可以是数组数据、JSON数据、函数数据、数据源对象(Event Source Object) $('#calendar').fullCalendar({ eventSources: [ '/feed1.php', '/feed2.php' ] });allDayDefault allDayDefault 决定了在 Event Object 的 allday属性未指定时的默认值。allDayDefault 值为布尔类型,默认true。 startParam 使用json接口的时候,定义开始时间(ISO8601时间字符串)的属性名。值为字符串类型的,默认为'start'。 endParam 使用json接口的时候,定义结束时间(ISO8601时间字符串)的属性名。值为字符串类型的,默认为'end'。 timezoneParam 使用json接口的时候,定义时区。值为字符串类型的,默认为'timezone'。 lazyFetching 是否延迟加载数据,值为布尔类型,默认值为true。 当定义为true的时候,FullCalendar 只有在真正需要的时候才去加载数据。例如,当你的日程表现在在月视图的二月,FullCalendar 会取整个二月的数据,在内部缓存起来,当用户切换到二月的周视图或者天视图的时候,FullCalendar 会自动从缓存中取得需要的数据。 当设置为false的时候,每次切换 FullCalendar 都会重新加载数据(不使用缓存)。 defaultTimedEventDuration 当没有设置事件的结束时间end时指定事件的持续时间,默认'02:00:00'即2小时。 defaultAllDayEventDuration 当事件为全天事件而没有设置结束end时间时指定事件的持续时间。默认是{ days: 1 }。 forceEventDuration 如果未指定事件end结束时间,是否强制使用结束时间。默认false。 eventDataTransform 回调函数,将自定义数据转换为标准的事件对象Event Object。 function( eventData ) {}该钩子函数(hook)允许您从JSON提要或其他事件源接收任意事件数据,并将其转换为FullCalendar接受的数据类型。 这让您轻松接受替代数据格式,而无需编写完全自定义的事件功能。 loading 回调函数,当获取数据开始和结束的时候触发: function( isLoading, view )AJAX开始获取数据的时候 isLoading 是true,结束的时候是false。view是当前的 View Object。此函数常常用来显示或隐藏加载图标。 updateEvent 方法,当更新事件时将事件渲染在日历上。 .fullCalendar( 'updateEvent', event )event必须是日程的原生Event Object,可以通过 eventClick 回调或者 clientEvents 方法获得: $('#calendar').fullCalendar({ eventClick: function(event, element) { event.title = "CLICKED!"; $('#calendar').fullCalendar('updateEvent', event); } });updateEvents 方法,当要更新多个事件并且渲染到日历时使用。 .fullCalendar( 'updateEvents', events )clientEvents 方法,从FullCalendar 的缓存的数据中取得日历事件。 .fullCalendar( 'clientEvents' [, idOrFilter ] ) -> Array此方法会从客户端缓存中获取 Event Objects 数组。 如果忽略idOrFilter参数的话,会取得全部数据。如果idOrFilter 是ID的话,会返回该ID的所有日程。idOrFilter 也可以是一个筛选函数,接受 Event Object 参数,返回布尔类型参数。 removeEvents 方法,删除Fullcalendar中的事件。 .fullCalendar( 'removeEvents' [, idOrFilter ] )如果忽略idOrFilter参数的话,删除所有日程。如果 idOrFilter是ID的话,会删除该ID的所有日程。idOrFilter 也可以是一个筛选函数,接受 Event Object 参数,返回布尔类型参数(如果是true的话就删除)。 refetchEvents 方法,从各个数据源重新获取并且渲染数据。 .fullCalendar( 'refetchEvents' )refetchEventSources 方法,重新获取一个或多个数据源。 .fullCalendar( 'refetchEventSources', sources )sources可以是单个事件id或者多个事件数组。 addEventSource 方法,动态的添加一个数据源。 .fullCalendar( 'addEventSource', source )数据源可以是一个数组,函数或者json接口。FullCalendar 会立刻从这个数据源获取日程并且渲染。 removeEventSource 方法,动态删除一个数据源。 .fullCalendar( 'removeEventSource', source )该数据源的事件会立刻从日历中移除。 removeEventSources 方法,动态删除所有事件源或多个指定的事件源。 .fullCalendar( 'removeEventSources', optionalSourcesArray )当optionalSourcesArray未指定,将删除所有的事件源。 getEventSources 方法,获取所有的事件源对象(Event Source Object),返回数组。 .fullCalendar( 'getEventSources' )getEventSourceById 方法,根据给定的时间id,检索获取事件源对象(Event Source Object) .fullCalendar( 'getEventSourceById', id ) |
CopyRight 2018-2019 实验室设备网 版权所有 |